﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace DataLoad.iContact.WinClient
{
    public partial class DLPicFrame : UserControl
    {
        private enum MoveMode
        {
            Normal,

            Position,

            Size
        }

        public DLPicFrame()
        {
            InitializeComponent();

            _x = 0;
            _y = 0;
        }

        private MoveMode _moveMode = MoveMode.Normal;

        [Description("Picture to be displayed")]
        public Image Picture
        {
            get
            {
                return _stockImage;
            }
            set
            {
                _stockImage = value;
                RemoveFrames();
            }
        }

        private Image _stockImage;

        private bool _stretched = false;

        [Description("Resize the picture to fit into the size of the control")]
        [DefaultValue(false)]
        public bool Stretched
        {
            get
            {
                return _stretched;
            }
            set
            {
                _stretched = value;
            }
        }

        private bool _keepAspectRatio = true;

        [Description("Keeps the aspect ratio of the selector frame")]
        [DefaultValue(true)]
        public bool KeepAspectRatio
        {
            get
            {
                return _keepAspectRatio;
            }
            set
            {
                _keepAspectRatio = value;
            }
        }

        private PictureBox _previewBox;

        [Description("PictureBox to show the preview of the selected frame")]
        public PictureBox PreviewBox
        {
            get
            {
                return _previewBox;
            }
            set
            {
                _previewBox = value;
            }
        }

        private Rectangle _rect;

        [Description("Frame rectangle")]
        public Rectangle FrameRectangle
        {
            get
            {
                return _rect;
            }
            set
            {
                RemoveFrames();
                _rect = value;
                if (_rect.Width == 0)
                {
                    _aspectRatio = 1;
                }
                else
                {
                    _aspectRatio = _rect.Height / _rect.Width;
                }
                DrawFrameRectangle(_rect);
                ShowPreview();
            }
        }

        private float _aspectRatio;

        // Convert and normalize the points and draw the reversible frame.
        private void DrawReversibleRectangle(Rectangle rect)
        {
            Rectangle rc = rect = RectangleToScreen(rect);

            // Draw the reversible frame.
            ControlPaint.DrawReversibleFrame(rc, Color.Black, FrameStyle.Thick);
        }

        private void DrawFrameRectangle(Rectangle rect)
        {
            using (Graphics g = CreateGraphics())
            {
                g.DrawRectangle(Pens.Black, rect);
                g.DrawRectangle(Pens.White, rect.X + 1, rect.Y + 1, rect.Width - 2, rect.Height - 2);

                Rectangle resize = new Rectangle(rect.Right - 7, rect.Bottom - 7, 7, 7);
                g.FillRectangle(Brushes.LightYellow, resize);
            }
        }

        private void RemoveFrames()
        {
            if (_stockImage != null)
            {
                using (Graphics g = CreateGraphics())
                {
                    if (_stretched)
                    {
                        g.DrawImage(_stockImage, 0, 0, Width, Height);
                    }
                    else
                    {
                        g.DrawImage(_stockImage, 0, 0);
                    }
                }
            }
        }

        private void DLPicEditor_MouseMove(object sender, MouseEventArgs e)
        {
            if (_rect != null)
            {
                switch (_moveMode)
                {
                    case MoveMode.Normal:
                        if ((e.X >= _rect.Left) && (e.X <= _rect.Right) && (e.Y >= _rect.Top) && (e.Y <= _rect.Bottom))
                        {
                            if ((e.X >= _rect.Right - 7) && (e.Y >= _rect.Bottom - 7))
                            {
                                Cursor.Current = Cursors.SizeNWSE;
                            }
                            else
                            {
                                Cursor.Current = Cursors.SizeAll;
                            }
                        }
                        break;

                    case MoveMode.Position:
                        Cursor.Current = Cursors.SizeAll;
                        DrawReversibleRectangle(_rect);

                        _rect.X = e.X - _x;
                        _rect.Y = e.Y - _y;

                        break;

                    case MoveMode.Size:
                        Cursor.Current = Cursors.SizeNWSE;
                        if ((e.X <= _rect.X) || (e.Y <= _rect.Y))
                        {
                            return;
                        }

                        DrawReversibleRectangle(_rect);


                        _rect.Width = e.X - _rect.X + 7;

                        if (!_keepAspectRatio)
                        {
                            _rect.Height = e.Y - _rect.Y + 7;
                        }
                        else
                        {
                            _rect.Height = (int)(_rect.Width * _aspectRatio);
                        }

                        break;

                    default:
                        break;
                }

                if (_moveMode != MoveMode.Normal)
                {
                    // Adjust the location
                    _rect.X = Math.Max(_rect.X, 0);
                    _rect.Y = Math.Max(_rect.Y, 0);

                    _rect.Width = Math.Min(_rect.Width, Width);
                    _rect.Height = Math.Min(_rect.Height, Height);

                    if ((_rect.X + _rect.Width) >= Width)
                    {
                        _rect.X = Width - _rect.Width;
                    }

                    if ((_rect.Y + _rect.Height) >= Height)
                    {
                        _rect.Y = Height - _rect.Height;
                    }

                    DrawReversibleRectangle(_rect);

                    ShowPreview();
                }
            }
        }

        private void ShowPreview()
        {
            if ((_previewBox != null) && (_stockImage != null))
            {
                using (Graphics g = _previewBox.CreateGraphics())
                {
                    g.DrawImage(GetImage(), 0, 0, _previewBox.Width, _previewBox.Height);
                }
            }
        }

        public Image GetImage()
        {
            if (_stockImage != null)
            {
                Bitmap bm = new Bitmap(_stockImage);
                float hRatio = (float)_stockImage.Height / (float)Height;
                float wRatio = (float)_stockImage.Width / (float)Width;

                Rectangle rc = new Rectangle((int)(_rect.X * wRatio), (int)(_rect.Y * hRatio), (int)(_rect.Width * wRatio), (int)(_rect.Height * hRatio));

                Bitmap newBm = bm.Clone(rc, bm.PixelFormat);

                using (Graphics g = Graphics.FromImage(bm))
                {
                    // Smooth the preview since it might be resized
                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                    g.DrawImage(newBm, 0, 0, _previewBox.Width, _previewBox.Height);
                }

                return newBm;
            }
            else
            {
                return null;
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            if (_stockImage != null)
            {
                RemoveFrames();

                DrawFrameRectangle(_rect);
            }
        }

        private int _x;

        private int _y;

        private void DLPicEditor_MouseDown(object sender, MouseEventArgs e)
        {
            if (_moveMode == MoveMode.Normal)
            {
                if ((e.X >= _rect.Left) && (e.X <= _rect.Right) && (e.Y >= _rect.Top) && (e.Y <= _rect.Bottom))
                {
                    if ((e.X >= _rect.Right - 7) && (e.Y >= _rect.Bottom - 7))
                    {
                        _moveMode = MoveMode.Size;
                    }
                    else
                    {
                        _moveMode = MoveMode.Position;
                    }
                }

                RemoveFrames();

                DrawReversibleRectangle(_rect);

                _x = e.X - _rect.X;
                _y = e.Y - _rect.Y;
            }
        }

        private void DLPicEditor_MouseUp(object sender, MouseEventArgs e)
        {
            _moveMode = MoveMode.Normal;

            _x = 0;
            _y = 0;

            DrawReversibleRectangle(_rect);

            DrawFrameRectangle(_rect);
        }
    }
}
